package cc.cix.hq.auth.service;

import cc.cix.hq.common.core.client.IMenuClient;
import cc.cix.hq.common.core.client.IUserClient;
import cc.cix.hq.common.core.entity.constant.AuthEventbus;
import cc.cix.hq.common.core.entity.org.User;
import cc.cix.hq.common.core.entity.org.event.LoginEvent;
import cc.cix.hq.common.core.exception.HqException;
import cc.cix.hq.common.core.utils.HqUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cix
 */
@Service
@RequiredArgsConstructor
public class MyUserDetailService implements UserDetailsService {

    @Reference
    private IUserClient userClient;
    @Reference
    private IMenuClient menuClient;

    private final KafkaTemplate<String, LoginEvent> kafkaTemplate;

    @SneakyThrows
    @Override
    public UserDetails loadUserByUsername(String username) {
        // 用户是否存在
        User user = userClient.getUserByMobile(username);
        if (user == null) {
            throw new HqException("用户不存在");
        }

        List<SimpleGrantedAuthority> grantedAuthorities = menuClient.listUserPermission(user.getId()).stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

        // 记录登录日志
        String ip = HqUtil.getHttpServletRequestIpAddress();

        LoginEvent loginEvent = new LoginEvent();
        loginEvent.setUsername(username);
        loginEvent.setIp(ip);
        loginEvent.setLoginTime(LocalDateTime.now());
        kafkaTemplate.send(AuthEventbus.LOGIN, loginEvent);

        return new org.springframework.security.core.userdetails.User(username, user.getPassword(), grantedAuthorities);
    }
}
